package com.yuyuan.user.utils;

import cn.hutool.core.util.StrUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicSessionCredentials;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.region.Region;
import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Response;
import com.yuyuan.common.utils.SystemConstants;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.net.URL;
import java.util.Date;
import java.util.TreeMap;

@Component
@EnableScheduling//开启定时任务
public class COSUtils {
    public static COSClient cosClient;

    /**
     * 获取COS访问临时密钥
     */
    public void getTmpInfo(){
        TreeMap<String, Object> config = new TreeMap<String, Object>();
        try {
            //申请身份数据
            String secretId = SystemConstants.TX_SECRET_ID;
            String secretKey = SystemConstants.TX_SECRET_KEY;

            config.put("secretId", secretId);
            config.put("secretKey", secretKey);

            //临时密钥有效时长，单位是秒，默认 1800 秒，目前主账号最长 2 小时（即 7200 秒），子账号最长 36 小时（即 129600）秒
            //目前为25小时有效期
            config.put("durationSeconds", 90000);

            // bucket
            config.put("bucket", "kestrel-1319254659");
            // bucket 所在地区
            config.put("region", "ap-guangzhou");

            // 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的具体路径
            // 列举几种典型的前缀授权场景：
            // 1、允许访问所有对象："*"
            // 2、允许访问指定的对象："a/a1.txt", "b/b1.txt"
            // 3、允许访问指定前缀的对象："a*", "a/*", "b/*"
            // 如果填写了“*”，将允许用户访问所有资源；除非业务需要，否则请按照最小权限原则授予用户相应的访问权限范围。
            config.put("allowPrefixes", new String[] {
                    "*"
            });

            // 密钥的权限列表。必须在这里指定本次临时密钥所需要的权限。
            // 简单上传、表单上传和分块上传需要以下的权限，其他权限列表请参见 https://cloud.tencent.com/document/product/436/31923
            String[] allowActions = new String[] {
                    // 简单上传
                    "name/cos:PutObject",
                    //下载
                    "name/cos:GetObject",
                    //删除
                    "name/cos:DeleteObject"
            };
            config.put("allowActions", allowActions);


            Response response = CosStsClient.getCredential(config);
            System.out.println("tmpSecretId: "+response.credentials.tmpSecretId);
            System.out.println("tmpSecretKey: "+response.credentials.tmpSecretKey);
            System.out.println("sessionToken: "+response.credentials.sessionToken);
            SystemConstants.TX_TMP_SECRET_ID = response.credentials.tmpSecretId;
            SystemConstants.TX_TMP_SECRET_KEY = response.credentials.tmpSecretKey;
            SystemConstants.TX_TMP_SESSION_TOKEN = response.credentials.sessionToken;
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException("no valid secret !");
        }
    }

    public static String getSign(String key, HttpMethodName method){
        //获取key对应的资源，有效期1min
        URL url = COSUtils.cosClient.generatePresignedUrl(SystemConstants.TX_BUCKET_NAME,
                key,
                new Date(System.currentTimeMillis() + 60 * 1000),
                method);
        return StrUtil.subAfter(url.toString(), "com/", true);
    }

    /**
     * 初始化COSClient
     * 定时任务，24h初始化一次，密钥的有效期为25h
     */
    @Scheduled(fixedRate = 24 * 60 * 60 * 1000)
    public void initCOSClient(){
        getTmpInfo();
        String tmpSecretId = SystemConstants.TX_TMP_SECRET_ID;
        String tmpSecretKey = SystemConstants.TX_TMP_SECRET_KEY;
        String sessionToken = SystemConstants.TX_TMP_SESSION_TOKEN;
        BasicSessionCredentials cred = new BasicSessionCredentials(tmpSecretId,tmpSecretKey,sessionToken);
        //设置地域
        Region region = new Region("ap-guangzhou");
        ClientConfig clientConfig = new ClientConfig(region);
        clientConfig.setHttpProtocol(HttpProtocol.https);
        cosClient = new COSClient(cred,clientConfig);
    }

}
